package tdengine

import (
	"FeedXmh/app/model"
	"database/sql"
	"fmt"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/os/gtime"
	"github.com/gogf/gf/util/gconv"
	_ "github.com/taosdata/driver-go/v3/taosRestful"
	"paco_toolkit/common"

	//_ "github.com/taosdata/driver-go/v3/taosSql"
	//_ "github.com/taosdata/driver-go/v3/taosWS"
	"time"
)

func CheckTaosDB() {
	//g.Log().Line(true).Debug("CheckTaosDB")
	err := model.TaosDB.Ping()
	if err != nil {
		g.Log().Line(true).Error(err.Error())
		model.TaosDB = GetTaosDb()
	} else {
		g.Log().Line(true).Debug("TaosDB Ping OK")
	}
}
func GetTaosDb() (taos *sql.DB) {
	var taosDSN = g.Cfg().GetString("taos.connect_str")
	taos, err := sql.Open("taosRestful", taosDSN)
	if err != nil {
		g.Log().Line(true).Errorf("failed to connect TDengine, err:%s", err.Error())
		return nil
	} else {
		return taos
	}
}

func TestTaos() {
	var taosDSN = g.Cfg().GetString("taos.connect_str")
	g.Log().Line(true).Info("DSN:%s", taosDSN)
	taos, err := sql.Open("taosRestful", taosDSN)
	if err != nil {
		g.Log().Line(true).Errorf("failed to connect TDengine, err:%s", err.Error())
		return
	}
	fmt.Println("TestTaos Connected")
	defer taos.Close()

	rows, err := taos.Query("SELECT `ts`,`current` FROM `meters` limit 200")
	if err != nil {
		g.Log().Line(true).Errorf("failed to select from table, err:%s", err.Error())
	}
	defer rows.Close()
	for rows.Next() {
		var r struct {
			ts      time.Time
			current float32
		}
		err := rows.Scan(&r.ts, &r.current)
		if err != nil {
			g.Log().Line(true).Error(err)
			return
		}
		g.Log().Line(true).Debug(r.ts, r.current)
		//log.Println(r.ts, r.current)
	}
}

func UpdateRecord() {

	now := gtime.Now().TimestampMilli()
	sql := fmt.Sprintf("INSERT INTO d1001 VALUES (%d, 10.2, 219, 0.32);", now)
	res, err := model.TaosDB.Exec(sql)
	if err != nil {
		g.Log().Line(true).Errorf("failed to select from table, err:%s", err.Error())
	} else {
		g.Log().Line(true).Debug(res.LastInsertId())
	}
}

func InsertRecordBak(item gdb.Map) (isok bool, err error) {
	var taosDSN = g.Cfg().GetString("taos.connect_str")
	g.Log().Line(true).Debugf("DSN:%s", taosDSN)
	taos, err := sql.Open("taosRestful", taosDSN)
	if err != nil {
		g.Log().Line(true).Errorf("failed to connect TDengine, err:%s", err.Error())
		return
	}
	g.Log().Line(true).Debug("TDengine Connected")
	defer taos.Close()

	sql := ""

	sn := gconv.String(item["sn"])
	addr := gconv.String(item["addr"])

	readtime := gtime.Now().TimestampMilli()
	rid := gconv.Uint32(item["rid"])
	hnum := gconv.String(item["hnum"])
	rectime := gtime.NewFromStr(gconv.String(item["rectime"])).TimestampMilli()
	mode := gconv.Int(item["mode"])
	flag_mode := gconv.Int(item["flag_mode"])
	flag_mode_bits := gconv.String(item["flag_mode_bits"])
	flag1 := gconv.Int(item["flag1"])

	cnt_gap_time := gconv.Int(item["cnt_gap_time"])
	emergency := gconv.Int(item["emergency"])
	event := gconv.String(item["event"])
	feed_type := gconv.Int(item["feed_type"])
	begin_end := gconv.Int(item["begin_end"])
	_err := gconv.Int(item["err"])
	auto := gconv.Int(item["auto"])
	food_left := gconv.Int(item["food_left"])
	remote := gconv.Int(item["remote"])
	tb := gconv.Int(item["tb"])
	tb_record := gconv.Int(item["tb_record"])
	max_feed := gconv.Float32(item["max_feed"])
	amount := gconv.Float32(item["amount"])
	day_use_feed := gconv.Float32(item["day_use_feed"])
	day_use_water := gconv.Float32(item["day_use_water"])
	v22 := gconv.Float32(item["v22"])
	i41 := gconv.Float32(item["i41"])
	vin := gconv.Float32(item["vin"])
	vin_calc := gconv.Float32(item["vin_calc"])
	motor_vol := gconv.Float32(item["motor_vol"])
	motor_cur := gconv.Float32(item["motor_cur"])
	step_mr := gconv.Int(item["step_mr"])
	debug := gconv.Int(item["debug"])

	sql = fmt.Sprintf(` INSERT INTO node_%s USING t_hzfgw_record 
     TAGS('%s','%s')  
 VALUES (%d, 
     %d,
     '%s',
     %d,
     %d,
     %d,
     '%s',
     %d,
     %d,
     %d,
     '%s',
     %d,
     %d,
     %d,
     %d,
     %d,
     %d,
     %d,
     %d,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %d,
     %d
     ) `, sn, addr, sn,
		readtime,
		rid,
		hnum,
		rectime,
		mode,
		flag_mode,
		flag_mode_bits,
		flag1,
		cnt_gap_time,
		emergency,
		event,
		feed_type,
		begin_end,
		_err,
		auto,
		food_left,
		remote,
		tb,
		tb_record,
		max_feed,
		amount,
		day_use_feed,
		day_use_water,
		v22,
		i41,
		vin,
		vin_calc,
		motor_vol,
		motor_cur,
		step_mr,
		debug)

	_, err = taos.Exec(sql)
	if err != nil {
		g.Log().Line(true).Error(err.Error())
	} else {
		g.Log().Line(true).Debug("save ok")
		isok = true
	}
	return isok, err
}

func InsertRecord(item gdb.Map) (isok bool, err error) {

	sql := ""

	sn := gconv.String(item["sn"])
	addr := gconv.String(item["addr"])

	readtime := gtime.Now().TimestampMilli()
	rid := gconv.Uint32(item["rid"])
	hnum := gconv.String(item["hnum"])
	rectime := gtime.NewFromStr(gconv.String(item["rectime"])).TimestampMilli()
	mode := gconv.Int(item["mode"])
	flag_mode := gconv.Int(item["flag_mode"])
	flag_mode_bits := gconv.String(item["flag_mode_bits"])
	flag1 := gconv.Int(item["flag1"])

	cnt_gap_time := gconv.Int(item["cnt_gap_time"])
	emergency := gconv.Int(item["emergency"])
	event := gconv.String(item["event"])
	feed_type := gconv.Int(item["feed_type"])
	begin_end := gconv.Int(item["begin_end"])
	_err := gconv.Int(item["err"])
	auto := gconv.Int(item["auto"])
	food_left := gconv.Int(item["food_left"])
	remote := gconv.Int(item["remote"])
	tb := gconv.Int(item["tb"])
	tb_record := gconv.Int(item["tb_record"])
	max_feed := gconv.Float32(item["max_feed"])
	amount := gconv.Float32(item["amount"])
	day_use_feed := gconv.Float32(item["day_use_feed"])
	day_use_water := gconv.Float32(item["day_use_water"])
	v22 := gconv.Float32(item["v22"])
	i41 := gconv.Float32(item["i41"])
	vin := gconv.Float32(item["vin"])
	vin_calc := gconv.Float32(item["vin_calc"])
	motor_vol := gconv.Float32(item["motor_vol"])
	motor_cur := gconv.Float32(item["motor_cur"])
	step_mr := gconv.Int(item["step_mr"])
	debug := gconv.Int(item["debug"])

	sql = fmt.Sprintf(` INSERT INTO node_%s_%s USING t_hzfgw_record 
     TAGS('%s','%s')  
 VALUES (%d, 
     %d,
     '%s',
     %d,
     %d,
     %d,
     '%s',
     %d,
     %d,
     %d,
     '%s',
     %d,
     %d,
     %d,
     %d,
     %d,
     %d,
     %d,
     %d,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %.3f,
     %d,
     %d
     ) `, addr, sn, addr, sn,
		readtime,
		rid,
		hnum,
		rectime,
		mode,
		flag_mode,
		flag_mode_bits,
		flag1,
		cnt_gap_time,
		emergency,
		event,
		feed_type,
		begin_end,
		_err,
		auto,
		food_left,
		remote,
		tb,
		tb_record,
		max_feed,
		amount,
		day_use_feed,
		day_use_water,
		v22,
		i41,
		vin,
		vin_calc,
		motor_vol,
		motor_cur,
		step_mr,
		debug)

	_, err = model.TaosDB.Exec(sql)
	if err != nil {
		g.Log().Line(true).Error(err.Error())
	} else {
		g.Log().Line(true).Debug("save ok")
		isok = true
	}
	return isok, err
}

func InsertDeviceAlarmHis(farmid string, houseid string, device_type string, device_addr string, sn string, add_time int64, level int, _type int, subtype int, alarm_content string, remark string, status int, cancel_time int64, confirm_status int, confirm_time int64, confirm_user string) (isok bool, err error) {

	sys_name := model.SysName

	sql := fmt.Sprintf(` INSERT INTO alarm_%s_%s_%s_%s_%s_%s USING t_device_alarm_his 
     TAGS('%s',%d,%d,'%s','%s','%s')  
 VALUES (
     %d,
     %d,
     %d,
     %d,
     '%s',
     '%s',
     %d,
     %d,
     %d,
     %d,
     '%s'
 ) `,
		sys_name, farmid, houseid, device_type, device_addr, sn,
		sys_name, gconv.Int(farmid), gconv.Int(houseid), device_type, device_addr, sn,
		add_time,
		level,
		_type,
		subtype,
		alarm_content,
		remark,
		status,
		cancel_time,
		confirm_status,
		confirm_time,
		confirm_user,
	)

	_, err = model.TaosDB.Exec(sql)
	if err != nil {
		g.Log().Line(true).Error(err.Error())
	} else {
		g.Log().Line(true).Debug("InsertDeviceAlarmHis save ok")
		isok = true
	}
	return isok, err

}

func TestInsertRecord() {
	var taosDSN = g.Cfg().GetString("taos.connect_str")
	g.Log().Line(true).Info("DSN:%s", taosDSN)
	taos, err := sql.Open("taosRestful", taosDSN)
	if err != nil {
		g.Log().Line(true).Errorf("failed to connect TDengine, err:%s", err.Error())
		return
	}
	fmt.Println("TestTaos Connected")
	defer taos.Close()
	readtime := gtime.Now().TimestampMilli()
	sn := "87250106"
	//_time := gtime.NewFromStr("2021-08-01 08:00:00").TimestampMilli()
	val := 1
	addr := "60003945"
	hnum := "A001"
	sql := fmt.Sprintf(" INSERT INTO node_%s "+
		"USING test TAGS('%s') "+
		"VALUES ("+
		"%d, "+
		"%d, "+
		"'%s'"+
		") ", sn, addr, readtime, val, hnum)
	_, err = taos.Exec(sql)
	if err != nil {
		g.Log().Line(true).Error(err.Error())
	} else {
		g.Log().Line(true).Debug("save ok")

	}
}

func AlterTable() {

	db := g.DB(g.Cfg().GetString("custom.db_name"))
	res, err := db.GetAll("select sn from t_hzfgw_node_para")
	if err != nil {
		g.Log().Line(true).Error(err)
	}
	for _, v := range res.List() {
		sn := gconv.String(v["sn"])
		sql := fmt.Sprintf("ALTER TABLE   `hozzen`.`node_%s` set tag `sn`='%s' ;", sn, sn)
		_, err := model.TaosDB.Exec(sql)
		if err != nil {
			//g.Log().Line(true).Error(err)
			g.Log().Line(true).Debugf("sn:%s alter err:%s", sn, err.Error())
		} else {
			g.Log().Line(true).Debugf("sn:%s alter ok", sn)
		}
	}
}

func DropTable() {

	db := g.DB(g.Cfg().GetString("custom.db_name"))
	res, err := db.GetAll("select sn from t_hzfgw_node_para")
	if err != nil {
		g.Log().Line(true).Error(err)
	}
	for key, v := range res.List() {
		sn := gconv.String(v["sn"])
		sql := fmt.Sprintf("DROP TABLE `hozzen`.`node_%s`", sn)
		_, err := model.TaosDB.Exec(sql)
		if err != nil {
			//g.Log().Line(true).Error(err)
			g.Log().Line(true).Debugf("sn:%s drop err:%s", sn, err.Error())
		} else {
			g.Log().Line(true).Debugf("sn:%s drop ok idx=%d", sn, key)
		}
	}
}

func ExitsRecord(sn string, rid uint32) (exist bool) {
	exist = false
	var taosDSN = g.Cfg().GetString("taos.connect_str")
	g.Log().Line(true).Debugf("DSN:%s", taosDSN)
	taos, err := sql.Open("taosRestful", taosDSN)
	if err != nil {
		g.Log().Line(true).Errorf("failed to connect TDengine, err:%s", err.Error())
		return
	}
	g.Log().Line(true).Debug("TDengine Connected")
	defer taos.Close()

	sql := fmt.Sprintf("SELECT count(0) as num FROM node_%s WHERE rid=%d ", sn, rid)
	rows, err := taos.Query(sql)
	defer rows.Close()
	if err != nil {
		g.Log().Line(true).Errorf("failed to select from table, err:%s", err.Error())
	} else {
		for rows.Next() {
			var num int
			err := rows.Scan(&num)
			if err != nil {
				g.Log().Line(true).Error(err)
				break
			}
			if num > 0 {
				exist = true
			}
		}
	}
	return exist
}

func GetLastRid(addr string) (rid uint64) {
	rid = 0

	sql := fmt.Sprintf("SELECT MAX(rid) as rid FROM `t_hzfgw_record` WHERE  addr in ('%s') ", addr)
	rows, err := model.TaosDB.Query(sql)
	defer rows.Close()
	if err != nil {
		g.Log().Line(true).Errorf("failed to select from table, err:%s", err.Error())
	} else {
		for rows.Next() {
			err := rows.Scan(&rid)
			if err != nil {
				g.Log().Line(true).Error(err)
				break
			}
		}
	}
	return rid

}

func GetRecords(sqlStr string) (list []model.Record) {

	rows, err := model.TaosDB.Query(sqlStr)
	defer rows.Close()
	if err != nil {
		g.Log().Line(true).Errorf("failed to select from table, err:%s", err.Error())
	} else {
		for rows.Next() {
			r := new(model.Record)
			err := rows.Scan(
				&r.Readtime,
				&r.Rid,
				&r.Hnum,
				&r.Rectime,
				&r.Mode,
				&r.Flag_mode,
				&r.Flag_mode_bits,
				&r.Flag1,
				&r.Cnt_gap_time,
				&r.Emergency,

				&r.Event,
				&r.Feed_type,
				&r.Begin_end,
				&r.Err,
				&r.Auto,
				&r.Food_left,
				&r.Remote,
				&r.Tb,
				&r.Tb_record,
				&r.Max_feed,

				&r.Amount,
				&r.Day_use_feed,
				&r.Day_use_water,
				&r.V22,
				&r.I41,
				&r.Vin,
				&r.Vin_calc,
				&r.Motor_vol,
				&r.Motor_cur,
				&r.Step_mr,

				&r.Debug,
				&r.Addr,
				&r.Sn,
			)
			if err != nil {
				g.Log().Line(true).Error(err)
				break
			}

			r.ReadtimeFormat = gtime.NewFromTimeStamp(r.Readtime.Unix()).Format(common.DATE_TIME_FORMAT)
			r.RectimeFormat = gtime.NewFromTimeStamp(r.Rectime.Unix()).Format(common.DATE_TIME_FORMAT)

			//r.ReadtimeFormat = r.Readtime.Format("2006-01-02 15:04:05")
			//r.RectimeFormat = r.Rectime.Format("2006-01-02 15:04:05")
			list = append(list, *r)
		}
	}

	return list
}

func GetCount(sqlStr string) (num int) {
	num = 0
	//统计查询语句的行数
	rows, err := model.TaosDB.Query(sqlStr)
	defer rows.Close()
	if err != nil {
		g.Log().Line(true).Errorf("failed to select from table, err:%s", err.Error())
	} else {
		for rows.Next() {
			err := rows.Scan(&num)
			if err != nil {
				g.Log().Line(true).Error(err)
				break
			}
		}
	}
	return num
}

func GetRecordsNew(sqlStr string) (list []map[string]interface{}) {
	rows, err := model.TaosDB.Query(sqlStr)
	defer rows.Close()
	if err != nil {
		g.Log().Line(true).Errorf("failed to select from table, err:%s", err.Error())
	} else {
		columns, _ := rows.Columns()
		columnLength := len(columns)
		cache := make([]interface{}, columnLength) //临时存储每行数据
		for index, _ := range cache {              //为每一列初始化一个指针
			var a interface{}
			cache[index] = &a
		}
		for rows.Next() {
			_ = rows.Scan(cache...)
			item := make(map[string]interface{})
			for i, data := range cache {
				item[columns[i]] = *data.(*interface{}) //取实际类型
			}
			list = append(list, item)
		}
	}
	return list
}
